<?php
/**
 * ワンタイムトークン操作ヘルパ
 *
 * @author hatanaka
 * @package Controller_Action_Helper
 * @subpackage Token
 */
class Controller_Action_Helper_Token extends Zend_Controller_Action_Helper_Abstract
{
	/**
	 * ワンタイムトークン名前空間
	 *
	 * @var string
	 */
	const SESSION_NAMESPACE_TOKEN = 'WEB_TOKEN';

	/**
	 * ワンタイムトークン有効期限 とりあえず3時間
	 * 60*60*3
	 * @var int
	 * 	 */
	protected static $_tokenExpire = 10800;

	/**
	 * @var Zend_Session_Namespace
	 */
	protected $_session;

	/**
	 * 名前空間
	 *
	 * @var string
	 */
	protected $_namespace = 'Default';

	/**
	 * 名前空間を変更します。
	 *
	 * @param string $namespace
	 * @return Controller_Action_Helper_Token
	 */
	public function setNamespace($namespace)
	{
		if(!is_string($namespace) || !strlen($namespace)){
			throw new Exception('名前空間が文字列じゃない、もしくは空文字');
		}
		
		$this->_namespace = $namespace;
		return $this;
	}

	/**
	 * コンストラクタ
	 *
	 * @throws Exception
	 * @return void
	 */
	final public function __construct()
	{
		// セッションの名前空間生成
		$this->_session = new Zend_Session_Namespace(self::SESSION_NAMESPACE_TOKEN, true);
	}

	/**
	 * ワンタイムトークンを作成します。
	 *
	 * @param string optional $nameSpace 名前空間
	 * @return string
	 */
	public function create($namespace = null)
	{
		if (is_null($namespace)) {
			$namespace = $this->_namespace;
		}

		if (!is_null($this->_session) && isset($this->_session->_namespace[$namespace])) {
			// ワンタイムトークンを削除
			$this->deleteToken($namespace);
		}

		// ワンタイムトークンを生成
		$this->_session->_namespace[$namespace] = hash('sha256', uniqid(mt_rand(), true), false);

		return $this->_session->_namespace[$namespace];
	}

	/**
	 * ワンタイムトークンが正しいか判定します。
	 * @param string $prmToken
	 * @param string optional $nameSpace 名前空間
	 * @return bool
	 */
	public function isValid($prmTkn, $namespace = null)
	{
		if (is_null($namespace)) {
			$namespace = $this->_namespace;
		}

		// パラメータで渡されたワンタイムトークンまたはセッションに保持中のワンタイムトークンの値がnullまたは空の場合、常にfalseを返す
		if (is_null($this->_session)) {
			return false;
		}
		if (!strlen($prmTkn) || !strlen($this->_session->_namespace[$namespace])) {
			return false;
		}

		if ((string)$this->_session->_namespace[$namespace] == (string)$prmTkn) {
			return true;
		}
		else {
			return false;
		}
	}

	/**
	 * ワンタイムトークンを削除します。
	 *
	 * @param string optional $token
	 * @return void
	 */
	public function deleteToken($namespace = null)
	{
		if (is_null($namespace)) {
			$namespace = $this->_namespace;
		}

		// ワンタイムトークンがnullまたは空の場合何もしないで抜ける
		if (!is_null($this->_session) && isset($this->_session->_namespace[$namespace])) {
			unset($this->_session->_namespace[$namespace]);
		}
	}
}
